﻿using Library.Test.Logic;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;

namespace Library.Test
{
    public class Program
    {
        private static void Main(string[] args)
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("开始测试!");
            Console.ResetColor();

            //显示环境信息
            //ShowEnvironmentDetails();
            //多线程测试
            //ThreadTest();

            //委托测试
            DelegateTest();

            Console.ReadLine();
        }

        /// <summary>
        /// 显示环境信息
        /// </summary>
        private static void ShowEnvironmentDetails()
        {
            //输出本机的驱动器以及有些有用的细节信息
            foreach (string drive in Environment.GetLogicalDrives())
            {
                Console.WriteLine("Drive:{0}", drive);//输出本机所有的驱动
                Console.WriteLine("OS:{0}", Environment.OSVersion);//输出本机的OS
                Console.WriteLine("Number of processors:{0}", Environment.ProcessorCount);//输出ProcessorCount
                Console.WriteLine(".NET 版本:{0}", Environment.Version);//输出.NET版本
                Console.WriteLine("ExitCode:{0}", Environment.ExitCode);//获取或设置应用程序中任何地方的退出代码
                Console.WriteLine("Digit:{0}", Environment.Is64BitOperatingSystem);//返回bool值,代表主机是否运行64位操作系统
                Console.WriteLine("当前机器的名字:{0}", Environment.MachineName);//获得当前机器的名字
                Console.WriteLine("当前环境的换行符:{0}", Environment.NewLine);//获得当前环境的换行符
                Console.WriteLine("通向系统目录的完整路径:{0}", Environment.SystemDirectory);//返回通向系统目录的完整路径
                Console.WriteLine("这个应用程序的用户的名称:{0}", Environment.UserName);//返回系统这个应用程序的用户的名称
            }
        }


        /// <summary>
        /// 多线程测试
        /// </summary>
        private static void ThreadTest()
        {
            Console.WriteLine("多线程测试开始!");
            ThreadTestService threadTestService = new ThreadTestService();

            threadTestService.SingleThread();

            threadTestService.ParallelThread();
        }


        /// <summary>
        /// 委托测试
        /// </summary>
        private static void DelegateTest()
        {
            //委托
            DelegateTestService delegateTestService = new DelegateTestService();

            //Invoke Invoke()是主要的方法,用于调用委托维护的每个方法.向所有同步调用一样,方法会阻塞调用者直到它执行完毕.Invoke方法也不必显式的调用,它工作于后台.
            #region Invoke
            ////*****************************第一种，是直接将方法给委托【也相当于在外部直接申明事件】
            //ProcessDelegate<string, int> processDelegate = delegateTestService.OutputStr;
            //var ss = new List<int>() { 2, 3, 4, 5 };
            //var str = processDelegate.Invoke("Invoke同步调用:委托", 1, ss);
            //Console.WriteLine(str);

            ////第二种是，已经实例化了一个事件，将将方法给事件
            //delegateTestService.delegateMethod = delegateTestService.OutputStr;
            //var delegateMethodStr = processDelegate("delegateMethodStr:委托", 2, ss);//Invoke方法也不必显式的调用,它工作于后台.
            //Console.WriteLine(delegateMethodStr);

            ////第三种方式，New一个委托对象，将方法当成参数，传递进去
            //delegateTestService.delegateMethod = new ProcessDelegate<string, int>(delegateTestService.OutputStr1);
            //var delegateMethodStr1 = delegateTestService.delegateMethod.Invoke("同步调用delegateMethodStr1:委托", 3, ss);
            //Console.WriteLine(delegateMethodStr1);
            #endregion

            #region 观察着模式
            //var carService = new CarService(15);//初始化车辆，并初始化油量
            //new CarAlerterService(carService);//给观察者【让观察者一直观察油量】
            //carService.Run(120);//启动以后，一直在降低油量，当观察者发现油量没了，就触发事件
            #endregion

            #region 转换大小写，匿名方式
            //string[] names = { "abCDefG", "HIJKlmnOP", "QRsTuvW", "XyZ" };
            //DelStrTo delStrTo = DelegateStrService.StrToLower;
            //delStrTo(names);
            //foreach (var item in names)
            //{
            //    Console.WriteLine(item);
            //}


            //delStrTo = new DelStrTo(DelegateStrService.StrToUpper);
            //delStrTo(names);
            //foreach (var item in names)
            //{
            //    Console.WriteLine(item);
            //}

            //DelegateStrTest(names, DelegateStrService.StrSYH);
            //foreach (var item in names)
            //{
            //    Console.WriteLine(item);
            //}

            /////匿名函数
            //DelegateSingleStrTest(names, delegate (string name) { return name.ToLower(); });
            //foreach (var item in names)
            //{
            //    Console.WriteLine(item);
            //}
            //DelegateSingleStrTest(names, (name) => {
            //    return name.ToLower();
            //});
            //foreach (var item in names)
            //{
            //    Console.WriteLine(item);
            //}

            //DelStrTo delSingleStrTo = (names) =>
            //{
            //    for (int i = 0; i < names.Length; i++)
            //    {
            //        names[i] = names[i].ToUpper();
            //    }
            //};
            //foreach (var item in names)
            //{
            //    Console.WriteLine(item);
            //}
            #endregion

            #region BeginInvoke EndIvoke
            //AsycDelegate myAsycDelegate = DelegateAsyService.AsyncMethod;//定义一个委托成员变量，这里用的是简
            //string fromAsyncMethrod=string.Empty;
            //IAsyncResult iAsyncRsl = myAsycDelegate.BeginInvoke(out fromAsyncMethrod, "toAsycMethod", null, null);//委托调用BeginInvoke返回IAsyncResult                                                                                                  
            ////主线程中........可在此段时间做其他的事
            //Thread.Sleep(2000);//主线程休息2秒钟
            //string returnStrFromAsyncMethod = myAsycDelegate.EndInvoke(out fromAsyncMethrod, iAsyncRsl);//调用EndInvoke返回最终结果
            //System.Console.WriteLine("the string return from AsyncMethod is {0}", returnStrFromAsyncMethod);
            //System.Console.WriteLine("the fromAsyncMethod is :{0}", fromAsyncMethrod);

            //三种标准的使用模式:
            //1 > wait - until - done等待直到完成模式,在产生一个异步方法的执行后(Beginnvoke()),初始线程做一些其他的处理,之后会挂起并等待异步方法的结束,以便继续执行.不同于同步方法的是同步方法一旦被调用便初始线程便不能做任何其他的处理-- - 控制完全转移到被调用的方法那里去了.（这个是两个方法都在执行，初始线程会在执行完别的节点后等待这个执行结果）
            //2 > Polling轮询模式,初始线程周期性的检查新生的线程是否完成了执行,没有的话继续其他的处理.（这个是两个方法都在执行，初始线程会定期检查不会停止）
            //3 > callback回调模式,初始线程不会等待或检查卵生线程是否完成了执行,而是: 当被委托引用的方法在卵生(spawned)线程中执行完成时,子线程会调用一个回调方法,该方法在调用EndInvoke()之前处理异步方法的调用结果.（在子线程中调用父线程的方法，父线程是被动的而不是主动的去验证）
            //（这个是两个方法都在执行，初始线程会在执行完别的节点后等待这个执行结果）
            //AsycTwoDelegate asycTwoDelegate = DelegateAsyService.AsyncMethodTwo;//定义一个委托成员变量，这里用的是简
            //IAsyncResult iAsyncRsl1 = asycTwoDelegate.BeginInvoke("twoAsycMethod", null, null);//委托调用BeginInvoke返回IAsyncResult
            ////等待子线程完成
            //while (!iAsyncRsl1.IsCompleted)
            //{
            //    Console.WriteLine("主线程中检查->:..异步调用的方法仍没有 完成...");
            //    for (long i = 0; i <= 100000000; i++) ;//做一些 自己的事，这里是空耗 cpu
            //}//轮询 结束时异步方法应已经完成了

            ////或者主线程中........可在此段时间做其他的事
            //Thread.Sleep(2000);//主线程休息2秒钟

            ///*此时可提起异步执行的结果了*/
            //string returnStr = asycTwoDelegate.EndInvoke(iAsyncRsl1);//调用EndInvoke返回最终结果
            //EndInvoke()方法被用于提取由异步执行的方法调用的返回值.且被线程用于释放资源。

            //*********************************************
            //上面程序总结：主程序调用委托方法，同时主程序可以休眠也可以继续执行别的程序。
            //子线程完成的是简单的线程等待休眠，完成父线程会调用子线程的BeginInvoke()和EndInvoke()方法最终获取返回值。
            //*********************************************

            //System.Console.WriteLine("returnStr {0}", returnStr);
            //关于IAsyncResult: 它是BeginInvoke()和EndInvoke()不可或缺的部分.BeginInvoke方法会返回一个AsyncResult类型的对象引用,该类AsyncResult实现了ISyncResult接口,AsyncReslut表示异步方法的状态,对该类需要知道以下重要特征:
            //1 > 当调用委托对象的BeginInvoke方法时系统创建一个该类的实例,将此对象的引用返回给ISyncResult 接口.
            //2 > AsyncResult对象 含有一AsyncDelegate的属性,它返回一个指向调用异步方法的委托的引用,该属性是AsyncResult 的属性而不是IAyncResult接口的属性.
            //3 > IsCompleted属性返回一个布尔值,表示异步方法是否被执行完毕.
            //4 > AsyncState属性返回一个作对象的引用,它会作为BeginInvoke方法的调用参数返回的引用是个Object类型.回调模式会用到它.

            //BeginInvoke EndIvoke
            //public IAsyncResult BeginInvoke(allDelegateInputRefAndOutParams,AsyncCallback cb, object state);//后两个方法需配合使用用于异步执行委托指向的方法. 他们会在独立的线程中执行.
            //public delegateReturnValue EndInvoke(allDelegateRefAndOutParams, IAsyncResult result);//将IAsyncResult最终转换成delegateReturnValue
            #endregion

            #region Action Func

            //DelegateActionFuncService.CatchLog(
            //()=> {
            //    Console.WriteLine("执行Action");
            //}, 
            //ex =>{
            //    Console.WriteLine("程序出现错误)");
            //}, "程序出现错误");

            //DelegateActionFuncService.CatchLog(
            //() => {
            //    Console.WriteLine("执行Action");
            //},
            //ex => {
            //    Console.WriteLine("程序出现错误)");
            //});

            var resultStr = DelegateActionFuncService.Catch<string, string>("我的",
                 (a) =>
                 {
                     return a + "错误信息";
                 },
                 ex =>
                 {
                     Console.WriteLine("程序出现错误)");
                 });

            Console.WriteLine(resultStr);

            #endregion
        }

        private static void DelegateStrTest(string[] name, DelStrTo del)
        {
            del(name); //委托需要一个参数，写入name
        }


        /// <summary>
        /// 匿名函数
        /// </summary>
        /// <param name="names"></param>
        /// <param name="del"></param>
        public static void DelegateSingleStrTest(string[] names, DelSingeStrTo del)
        {
            //del(name); //委托需要一个参数，写入name。
            for (int i = 0; i < names.Length; i++)
            {
                names[i] = del(names[i]);
            }
        }
    }
}
